<?php
/*使用说明
 * 使用前先根据自己的需求配置类成员属性，都列在类的开头部分了。
 * 第一步：声明对象，例如：$code=new VerificationCode(80,30,4);//参数为宽度，高度，字符数量，可留空，类有默认值。
 * 第二步：显示图像,例如：$code->showImage();
 * 第三步：取得验证码的字符串值：$code->getCode()，可根据自己的需求存放在session或cookies里面，以便验证;
 * 关于点击刷新验证码方法：给img标签添加一个onclick事件<img src="code.php" onclick="this.src='code.php?'+Math.random" />
 * 如果不明白怎么使用，建议你先复习下PHP关于类和session的知识。
 */
class VerificationCode {    
    
    private $ttf_dir="./";//字体文件存放路径，默认为当前父文件同一目录,斜杠结尾
    private $font_type="";//字体文件名，默认为空，例如：GiddyupStd.otf    
    //以下成员不用设置，乱设置可能导致功能异常
    private $width;//验证码宽度
    private $height;//验证码图像高度
    private $codenum;//验证码字符数
    private $im;//图像对象
    private $disturbColorNum;//干扰元素个数
    private $code;//验证码字符串
    
    function __construct($width=80,$height=30,$codenum=4)  {
        $this->width=$width;
        $this->height=$height;
        $this->codenum=$codenum;
        $this->disturbColorNum=min(floor($width*$height/15),225-$this->codenum);
        //生成验证文字
        $strs="23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
        
//        for($i=0;$i<$this->codenum;$i++){
//            $this->code.=$strs{rand(0,strlen($strs)-1)};
//        }
        $strs =  str_shuffle($strs);
        $this->code=substr($strs,0,$this->codenum);
    }   
    //取验证码的值，可保存到SESSION中以做验证
    function getCode(){
        return $this->code;
    }
    //显示验证码
    function showImage(){
        $this->_createImage();
        $this->_setDisturb();
        $this->_mkCode();
        $this->_output();        
    }
    
    private function _createImage(){
        //创建图像对象
        $this->im = imagecreatetruecolor($this->width, $this->height);//创建指定宽度高度的图像
        $backColor= imagecolorallocate($this->im, rand(200,255), rand(200,255), rand(200,255));
        imagefill($this->im, 0, 0, $backColor);//随机背景色
        $border=imagecolorallocate($this->im,0,0,0);
        imagerectangle($this->im, 0, 0, $this->width-1, $this->height-1, $border);//添加矩形黑色边框
    }
    private function _setDisturb(){
        //设置干扰元素
        for($i=0;$i<$this->disturbColorNum;$i++){//随机像素点
            $Color= imagecolorallocate($this->im, rand(0,255), rand(0,255), rand(0,255));
            imagesetpixel($this->im, rand(1, $this->width-2), rand(1, $this->height-2), $Color);
        }
        for($i=0;$i<5;$i++){
            $Color= imagecolorallocate($this->im, rand(0,255), rand(0,255), rand(0,255));
            imagearc($this->im, rand(-10, $this->width), rand(-10,$this->height), rand(30, $this->width), rand(20,  $this->height), 44, 200, $Color);
        }
    }
    private function _mkCode(){
        
        for($i=0;$i<$this->codenum;$i++){
            $fontcolor=  imagecolorallocate($this->im, rand(0, 100), rand(0, 100), rand(0, 100));   
            
            if($this->font_type!==""&&file_exists($this->ttf_dir.$this->font_type)){
                $fontsize=rand(14,16);
                $x=floor(($this->width-8)/$this->codenum)*$i+8;
                $y=rand($fontsize,$this->height);
                imagettftext($this->im, $fontsize, rand(-45, 45), $x, $y, $fontcolor, $this->ttf_dir.$this->font_type, $this->code{$i});
            }else{
                $fontsize=rand(4,5);
                $x=floor($this->width/$this->codenum)*$i+3;
                $y=rand(0, $this->height-15);
                imagechar($this->im, $fontsize, $x, $y, $this->code{$i}, $fontcolor);
            }
        }
    }
    
    private function _output(){
        //输出图像
        if(imagetypes() & IMG_PNG){
            header("Content-Type:image/png");
            imagepng($this->im);
        }elseif(imagetypes() & IMG_GIF){
            header("Content-Type:image/gif");
            imagegif($this->im);
        }elseif(imagetypes() & IMG_JPEG){
            header("Content-Type:image/jpeg");
            imagejpeg($this->im);
        }elseif(imagetypes() & IMG_WBMP){
            header("Content-Type:image/vnd.wap.wbmp");
            imagewbmp($this->im);
        }else{
            die("PHP不支持GIF,JPEG,PNG,WBMP中的任意一种格式图像创建，请检查服务器环境是否安装相关组件或扩展");
        }
        
    }    
    function __destruct() {
        imagedestroy($this->im);
    }
}

